#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;
#define max 1024

const char* get_username()
{
    const char* p=getenv("USER");
    return p;
}
const char* get_hosthome()
{
    const char* p=getenv("HOSTNAME");
    return p;
}
const char* get_pwd()
{
    const char* p=getenv("PWD");
    return p;
}
void get_command(char* command,size_t num)
{
    printf("[%s@%s %s]# ",get_username(),get_hosthome(),get_pwd());
    fgets(command,num,stdin);//fgets函数会读取\n
    command[strlen(command)-1]=0;

}
void get_split(char* in[],char out[])
{
    int argc=0;
    in[argc++]=strtok(out," ");
    while(in[argc++]=strtok(NULL," "));//未找到对应串时末尾会添加NULL
}
int lastcode = 0;
void my_exec(char* argv[])
{
    pid_t i=fork();
    if(i==0)//子进程
    {
        execvp(argv[0],argv);
        exit(-1);//进程没有成功切换
    }
    else//父进程
    {
        int status;
        int ret = waitpid(i,&status,0);
        if(ret==0)
            cout<<"出错"<<endl;
        else 
            lastcode=WEXITSTATUS(status);
    }
}

char mycwd[512];//添加环境变量实质是添加地址，所以应始终有效
char myenv[150][100];int sz=0;//环境变量表
int deal(char* argv[])//内建命令就是bash自己内部函数执行的命令，不是bash子进程
{
    if(strcmp(argv[0],"cd")==0)
    {
        if(!argv[1]) return 1;
        chdir(argv[1]);//改变当前工作目录(..)

        //处理环境变量里的PWD
        char tmp[512];//临时变量存放
        getcwd(tmp,sizeof(tmp));//将当前进程相对路径转为绝对路径存入tmp中
        sprintf(mycwd,"PWD=%s",tmp);//存进全局变量中（地址）
        putenv(mycwd);
       
        return 1;
    }
    else if(strcmp(argv[0],"export")==0)
    {
        if(!argv[1]) return 1;
        strcpy(myenv[sz],argv[1]);
        putenv(myenv[sz]);
        sz++;

        return 1;
    }
    else if(strcmp(argv[0],"echo")==0)
    {
        if(!argv[1]) {
            cout<<endl;
            return 1;
        }

        char* tmp=argv[1]+1;//取得$后面的数据
        if(strcmp(tmp,"?")==0){
            cout<<lastcode<<endl;
            lastcode=0;
        }
        else if(argv[1][0]=='$')//打印环境变量
        {
            cout<<getenv(tmp)<<endl;
        }
        else{
            cout<<argv[1]<<endl;
        }
        return 1;
    }
    return 0;
}

int main()
{
    while(1)
    {
        char command[max];
        char* argv[max];

        //接收命令行内容
        get_command(command,max);
        if(strlen(command)==0)//此时命令行中仅仅输入回车键
            continue;

        //拆分命令行
        get_split(argv,command);

        //进程切换调用
        int ret = deal(argv);//先判断是不是内建命令
        if(ret==1) continue;//是内建命令就不用让子进程去执行
        my_exec(argv);//创建子进程并替换执行
    }

    return 0;
}
